package main

import (
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"math"
	"net/http"
	"strings"
	"zinc-sync-tool/tools"
)
var tableName string
var indexName string
func main() {
	flag.StringVar(&tableName, "tableName", "", "tableName是要同步的表")
	flag.StringVar(&indexName, "indexName", "", "indexName是要同步的表的zinc上的名称")
	flag.Parse()
	if len(tableName) == 0 {
		fmt.Println("tableName is empty")
		return
	}
	if len(indexName) ==0 {
		indexName = tableName
	}
	env :=tools.GetConfig()
	Sync(env.ZincHost,env.ZincAdminName,env.ZincAdminPass,indexName,tableName)
	fmt.Println("Sync success")
}
// RetrieveMap SQL查询结果输出为Map
func RetrieveMap(db *sql.DB, sSql string) ([]map[string]interface{}, error) {

	// 准备查询语句
	stmt, err := db.Prepare(sSql)
	if err != nil {
	   fmt.Println(err)
	   return nil, err
	}
	defer stmt.Close()
 
	// 查询
	rows, err := stmt.Query()
	if err != nil {
	   fmt.Println(err)
	   return nil, err
	}
	defer rows.Close()
 
	// 数据列
	columns, err := rows.Columns()
	if err != nil {
	   fmt.Println(err)
	   return nil, err
	}
 
	// 列的个数
	count := len(columns)
 
	// 返回值 Map切片
	mData := make([]map[string]interface{}, 0)
	// 一条数据的各列的值（需要指定长度为列的个数，以便获取地址）
	values := make([]interface{}, count)
	// 一条数据的各列的值的地址
	valPointers := make([]interface{}, count)
	for rows.Next() {
 
	   // 获取各列的值的地址
	   for i := 0; i < count; i++ {
		  valPointers[i] = &values[i]
	   }
 
	   // 获取各列的值，放到对应的地址中
	   rows.Scan(valPointers...)
 
	   // 一条数据的Map (列名和值的键值对)
	   entry := make(map[string]interface{})
 
	   // Map 赋值
	   for i, col := range columns {
		  var v interface{}
 
		  // 值复制给val(所以Scan时指定的地址可重复使用)
		  val := values[i]
		  b, ok := val.([]byte)
		  if ok {
			 // 字符切片转为字符串
			 v = string(b)
		  } else {
			 v = val
		  }
		  entry[col] = v
	   }
 
	   mData = append(mData, entry)
	}
 
	return mData, nil
}



func Sync(host string,adminName string,adminPass,indexName string,tableName string) bool {
	db := tools.GetDB()
	url := host+"/api/"+indexName+"/_doc"
	
   	method := "PUT"

	// fmt.Println(configs.App.MysqlDns)
	limit :=100 
	ct :=int64(0)
	db.Table(tableName).Count(&ct)
	
	pageCount :=int(math.Ceil(float64(ct)/float64(limit)))
	if pageCount ==0 && ct > 0 {
		pageCount = 1
	}

	indexRunning :=0

	for i := 0; i < pageCount; i++ {
		
		
		// fmt.Println(i,pageCount)
		
		sql :="select * from "+tableName+" limit "+fmt.Sprintf("%d",(limit))+" offset "+fmt.Sprintf("%d",(i*limit))

		

		cs ,_:=RetrieveMap(db.DB(),sql)
		
		for _, cc := range cs {
			bt ,_:=json.Marshal(cc)
			indexRunning++
			fmt.Printf("-----------%s------total-------%d-----processing---%d---------",tableName,ct,indexRunning)
				
			payload := strings.NewReader(string(bt))
			client := &http.Client {
			}
			req, err := http.NewRequest(method, url, payload)
			if err != nil {
			   fmt.Println(err)
			   continue
			}
			passStr :=adminName+":"+adminPass
			base64Auth :="Basic "+ base64.StdEncoding.EncodeToString([]byte(passStr))
			req.Header.Add("Authorization", base64Auth)
			req.Header.Add("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
			req.Header.Add("Content-Type", "application/json")
			req.Header.Add("Accept", "*/*")
			req.Header.Add("Host", host)
			req.Header.Add("Connection", "keep-alive")
		 
			res, err := client.Do(req)
			if err != nil {
			   fmt.Println(err)
			   continue
			}
			defer res.Body.Close()
		 
			body, err := io.ReadAll(res.Body)
			if err != nil {
			   fmt.Println(err)
			   continue
			}
			fmt.Println(string(body))
			// resultMap :=make(map[string]interface{})
			// json.Unmarshal(body,&resultMap)
			 
			
		}
	}

	

	return true
}
